Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement SVCB #1067

Merged
merged 92 commits into from
Oct 11, 2020
Merged

Implement SVCB #1067

merged 92 commits into from
Oct 11, 2020

Conversation

DesWurstes
Copy link
Contributor

@DesWurstes DesWurstes commented Dec 30, 2019

Resolves #1064

Seems to work well. Can be tested with @ghedo's python code and his Go code (Now my code uses the same numbers. I've updated his Go code, below, to work with the new edns-like code:)

package main

import (
	"fmt"
	"github.com/DesWurstes/dns"
	"net"
	"sync"
)

func handleRequest(w dns.ResponseWriter, r *dns.Msg) {
	fmt.Println("GOT REQUEST", r)

	m := new(dns.Msg)
	m.SetReply(r)

	svcb := &dns.SVCB{
		Hdr: dns.RR_Header{
			Name:   r.Question[0].Name,
			Rrtype: dns.TypeSVCB,
			Class:  dns.ClassINET,
			Ttl:    3600,
		},
		Priority: 1,
		Target:   ".",
		Value: []dns.SVCBKeyValue{
			&dns.SVCBAlpn{
				Alpn: []string{"h2", "h3"},
			},
			&dns.SVCBPort{
				Port: 117,
			},
			&dns.SVCBIPv4Hint{
				Hint: []net.IP{net.IPv4(1, 1, 1, 1), net.IPv4(1, 1, 1, 2)},
			},
			&dns.SVCBECHConfig{
				ECH: []byte{1, 2},
			},
		},
	}

	m.Answer = append(m.Answer, svcb)
	err := w.WriteMsg(m)
	if err != nil {
		fmt.Println(err)
	}
}

func main() {
	var wg sync.WaitGroup
	wg.Add(1)

	dns.HandleFunc("svcb.example.", handleRequest)

	server := &dns.Server{Addr: ":53", Net: "udp"}
	go server.ListenAndServe()

	wg.Wait()
}

@codecov-io
Copy link

codecov-io commented Dec 30, 2019

Codecov Report

Merging #1067 into master will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #1067   +/-   ##
=======================================
  Coverage   56.09%   56.09%           
=======================================
  Files          42       42           
  Lines       10612    10612           
=======================================
  Hits         5953     5953           
  Misses       3609     3609           
  Partials     1050     1050           

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6233703...6233703. Read the comment docs.

scan_rr.go Outdated Show resolved Hide resolved
types.go Outdated Show resolved Hide resolved
@miekg
Copy link
Owner

miekg commented Dec 30, 2019 via email

@miekg
Copy link
Owner

miekg commented Dec 30, 2019 via email

@DesWurstes
Copy link
Contributor Author

Thank you, that helps, I'll add that.

@miekg
Copy link
Owner

miekg commented Dec 30, 2019 via email

@DesWurstes
Copy link
Contributor Author

Hello again, I'm adding key=value wire encoding/decoding. In #1064 you suggested those key=value pairs should be []string in the struct. I believe []byte (or even a separated [][]byte) in the wireformat would suit better, because it'd allow the library to be used as a proxy with reserved and private key types (otherwise we can't deserialize the value, which is of an unknown format). In addition, packing and unpacking would be more expensive, which I think is used more often than string serialization/deserialization. Do you agree, should the struct keep Values as binary?

@miekg
Copy link
Owner

miekg commented Dec 31, 2019 via email

@ghedo
Copy link

ghedo commented Apr 2, 2020

Hello @DesWurstes, are you still working on this by any chance? I'm interested in helping out (if any help is needed) to get this in shape (if you are not interested in working on this anymore I'm also available to take over the work and get it ready, if that's ok with you).

We (Cloudflare) are looking into shipping support for HTTSSVC, so this would help greatly.

Implements for draft-ietf-tls-esni-05, thus if we don't declare it private people will try to use with Cloudflare's servers, which are draft-ietf-tls-esni-02 that is incompatible with the SVCB record.

I don't understand this part. Why does it need to be "private"? If people try to query SVCB or HTTPSSVC records on Cloudflare's DNS servers they will get back nothing, as we don't currently serve these records. In that case a client wouldn't use an ESNI version that Cloudflare servers don't support, and it could either fallback to an older version if it supports it, or not do ESNI at all.

@DesWurstes
Copy link
Contributor Author

Hello,

My implementation was incomplete because I wasn't sure if the specification would undergo major changes. It seems it has matured. Now I'll rebase it and start working on it again.

I'll change

Value    []string `dns:"txt"`

to

Value    []uint16 `dns:"svcb"`

so that it doesn't decode when not needed. (and define the type)

I wanted to make it private as the draft is not finalized so no server supports it, and those implementing SNI encryption could try to use the SVCB record instead of _sni.

@DesWurstes
Copy link
Contributor Author

DesWurstes commented Apr 3, 2020

@miekg should I make Value field closer to the wireformat or the presentation format? (I prefer wireformat even though other ones seem to be keeping data in base64 strings instead of byte arrays but SvcValueField can be containing a key whose String name we don't know because it's reserved, thus it'd be nonconvertible to presentation format, but we shouldn't need to process SvcValueField unless .String(), to keep reserved keys when serializing to wireformat again?)

@miekg
Copy link
Owner

miekg commented Apr 5, 2020 via email

@DesWurstes
Copy link
Contributor Author

DesWurstes commented Apr 9, 2020

type SvcKeyValue struct {
	SvcParamKey   uint16
	SvcParamValue string
}

where SvcParamValue is the presentation format representation is fine? Then for defined keys we can add

func (rr *SVCB) getIpv4Hint() (ip net.IP, has bool) {
	...
}

etc, because the presentation format usually is helpful, but if they need it in go data types, they can call functions similar to this. (Or functions taking []SvcKeyValue as arguments, so that it's valid for both SVCB and HTTPSSVC)

Or to solve the problem similar to edns.go? For someone needing to use SVCB the EDNS approach could look too complex?

@miekg
Copy link
Owner

miekg commented Apr 10, 2020 via email

@DesWurstes
Copy link
Contributor Author

DesWurstes commented Apr 10, 2020

The array of SvcKeyValues would is in increasing order, they can for-loop until SvcParamKey == SVC_PORT (keys) for example. Do you prefer:

type SVCB struct {
	Hdr      RR_Header
	Priority uint16
	Target   string        `dns:"domain-name"`
	esni       ESNI `dns:"-"`
        Ipv4hint Ipv4 `dns:"-"`
        Alpn        alpn `dns:"-"`
        Nodefprotocol bool `dns:"-"`
        // other valuews
	Value    []SvcKeyValue `dns:"svc"` // if priority == 0 this is empty
}

@miekg
Copy link
Owner

miekg commented Apr 10, 2020 via email

@DesWurstes
Copy link
Contributor Author

That was an example of solution, the specification didn't change. In other words, should we keep values in SvcFieldValue struct in the presentation format as string, with conversion functions to go types, or when decoding it should we fill, with values, go-typed spaces in our struct, which are empty when a relevant key=value pair is not found?

Copy link

@ghedo ghedo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello again,

I've tested this code against my own implementation (written in Python) from rthalley/dnspython#452 (see comment below for a bug I found). The test I did involved running a Go server that serves an SVCB record, and a Python client that queries the record. Hoepfully this can be useful during developement of this PR, so I'll leave the code I wrote below. It currently only tests the alpn parameter, but it can be easily adapted to test other features as well.

In terms of the exposed Go API, I agree that using only string for all SvcParamValues is not great, as the user will need to know how to manually encode and decode all different values to/from the wire format (which is also different from the presentation format) for most fields. This becomes repetitive as each user will need to basically re-implement the same thing over and over.

I'm not sure using hard-coded fields as suggested in #1067 (comment) would work, as all the parameters are actually optional, so it's not clear to me how a user parsing an SVCB answer would know which parameter is actually set and which isn't (maybe using nullable pointers would work better?).

Given this and the fact that each field type has different presentation and wire formats, I think implementing something like edns.go would actually be much easier for users to use. Each svc param would implement a common interface, and the user could more easily create and use the different parameter I think (and it would also be easier to add new parameters in the future).

Anyways, thanks for working on this @DesWurstes.

Here is the code for the Go server in my test:

package main

import "fmt"
import "sync"

import "github.com/DesWurstes/dns"

func handleRequest(w dns.ResponseWriter, r *dns.Msg) {
    fmt.Println("GOT REQUEST", r)

    m := new(dns.Msg)

    m.SetReply(r)

    svcb := &dns.SVCB{
        Hdr: dns.RR_Header{
            Name:   r.Question[0].Name,
            Rrtype: dns.TypeSVCB,
            Class:  dns.ClassINET,
            Ttl:    3600,
        },
        Priority: 1,
        Target:   ".",
        Value:    []dns.SvcKeyValue {
            dns.SvcKeyValue{
                SvcParamKey:   dns.SVC_ALPN,
                SvcParamValue: "\x02h3\x02h2",
            },
        },
    }

    m.Answer = append(m.Answer, svcb)

    w.WriteMsg(m)
}

func main() {
    var wg sync.WaitGroup
    wg.Add(1)

    dns.HandleFunc("svcb.example.", handleRequest)

    server := &dns.Server{Addr: ":53", Net: "udp"}
    go server.ListenAndServe()

    wg.Wait()
}

And here is the Python client:

#!/usr/bin/env python3

import dns.resolver

resolver = dns.resolver.Resolver(configure=False)
resolver.nameservers = ['127.0.0.1']

answer = resolver.query('svcb.example.', 'SVCB')

print(answer.rrset)

msg_helpers.go Outdated

func packDataSvc(options []SvcKeyValue, msg []byte, off int) (int, error) {
for _, el := range options {
off, err := packUint16(el.SvcParamKey, msg, off)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that this is probably going to change anyway, but note that the off variable here shadows the off argument variable, so this function always ends up returning the same value that was passed in (effectively the svc fields are not encoded in the output message).

@ghedo
Copy link

ghedo commented Apr 17, 2020

Oh, regarding the dnspython code, note that I accidentally ended up using different code-points there than what is used in this PR, so one or the other needs to be manually changed to make the test work.

@DesWurstes
Copy link
Contributor Author

@miekg I'm ditto-ing edns.go, but I've found fields that have no use:

dns/edns.go

Lines 217 to 226 in 6737387

type EDNS0_SUBNET struct {
Code uint16 // Always EDNS0SUBNET
Family uint16 // 1 for IP, 2 for IP6
SourceNetmask uint8
SourceScope uint8
Address net.IP
}
// Option implements the EDNS0 interface.
func (e *EDNS0_SUBNET) Option() uint16 { return EDNS0SUBNET }

Code is only written to and never read (instead of .Option()). Should I not add this to SVCB (except local-experimental one)? (Are those fields only for backwards compatibility, or does that aim to remind the programmer that key is a part of the data stored too?)

svcb.go Outdated

// SvcKeyValue defines a key=value pair for SvcFieldValue.
// A SVCB RR can have multiple SvcKeyValues appended to it.
type SvcKeyValue interface {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh wow. I'm reading section 6 of the draft, that's pretty terrible range of things you can put in this record as key=value thingies.
Note that the EDNS0 stuff has been shown to be suboptimal and isn't the nicest interface to work with, so I rather not have it here again. Having different types implementing SvcKeyValue works for me, so this will be still an interface. However things like Key and Read look like overkill. I.e. the interface must be paired down to the absolute minimal

svcb.go Outdated
// e.Alpn = []string{"h2", "http/1.1"}
// o.Value = append(o.Value, e)
type SVC_ALPN struct {
Code uint16 // Always SVCALPN
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So Code isn't really need here? Maybe that can be the interface Code() uint ? Also the naming of the types should be move Go like and not uppercase with underscores (another mistake in the EDNS0 code). I'm not sure what would make sense here? A subpackage we're these things live? Or prefixing them with Svc ? Note that the final name is not chosen yet? (is this true?) So we might be looking into renaming this in the future

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than prefixing every member of each struct I'd prefer to move everything to a SVCB folder/subpackage. What do you think? The specification may be extended by much in the future.

I believe Key() should stay in the main interface, so that its exposed parts are

type SvcKeyValue interface {
	// Key returns the key code of the pair.
	Key() uint16
	// String returns the string representation of the value.
	String() string
}

@ghedo
Copy link

ghedo commented May 1, 2020

Just for the record, I was able to implement support for serving HTTPSSVC records in our internal DNS server after pulling these changes (including the latest API tweaks) 🎉 but I'll need to wait for this PR to be merged before starting deployment to production.

The new public API exposed to applications is quite nice, so I don't really have anything more to say 👍

@DesWurstes
Copy link
Contributor Author

DesWurstes commented May 1, 2020

Hi ghedo, thanks for the feedback you've given, and your dnspython SVCB code, it was essential for me to debug this implementation. :)

@miekg
Copy link
Owner

miekg commented May 6, 2020 via email

@miekg
Copy link
Owner

miekg commented May 6, 2020 via email

@DesWurstes
Copy link
Contributor Author

I was dreaming of keeping SVCB in types.go and moving everything related to the value field to a subpackage. For encode/decode and everything this would require everything in the KeyValuePair interface (Key, String,pack, unpack, read, len) to be declared public so that we can access it from the top package. We can't have a link between the package and the subpackage that is not exposed to the user. So I'd rather not move it to a subpackage. Do you have any solution ideas? Or we can move and then expose only 4 functions which we can mark "Internal, don't use" in the documentation?

@DesWurstes
Copy link
Contributor Author

DesWurstes commented Jul 26, 2020

@tmthrgd Thank you for the thorough review, I've addressed them all (or commented).

Copy link
Collaborator

@tmthrgd tmthrgd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few changes.

duplicate_generate.go Outdated Show resolved Hide resolved
msg_helpers.go Outdated Show resolved Hide resolved
svcb.go Outdated Show resolved Hide resolved
svcb.go Outdated Show resolved Hide resolved
svcb.go Outdated Show resolved Hide resolved
svcb.go Outdated
fallthrough
case '\\':
str.WriteByte('\\')
fallthrough
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I'm saying is replace this with:

case ...:
	str.WriteByte('\\')
	str.WriteByte(e)
default:
	str.WriteByte(e)

svcb.go Outdated
for _, e := range s.Data {
if (0x1f < e && e < 0x7f) || e == 0x09 {
switch e {
case '"', ';', ' ', '\\', 0x09:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can't be right for 0x09 (\t), because that would be \ (slash then tab).

svcb.go Outdated
var str strings.Builder
str.Grow(4 * len(s.Data))
for _, e := range s.Data {
if (0x1f < e && e < 0x7f) || e == 0x09 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we switch this around so it's like:

if e < ' ' || e > '~' {
	str.WriteString(escapeByte(e))
} else {
	...
}

svcb.go Outdated
// areSVCBPairArraysEqual checks if SVCBKeyValue arrays are equal
// after sorting their copies. arrA and arrB have equal lengths,
// otherwise zduplicate.go wouldn't call this function.
func areSVCBPairArraysEqual(arrA []SVCBKeyValue, arrB []SVCBKeyValue) bool {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They can share the same name: a = append(...).

svcb.go Outdated
func areSVCBPairArraysEqual(arrA []SVCBKeyValue, arrB []SVCBKeyValue) bool {
a := append(make([]SVCBKeyValue, 0, len(arrA)), arrA...)
b := append(make([]SVCBKeyValue, 0, len(arrB)), arrB...)
sort.Slice(a, func(i, j int) bool {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My suggestion here is just to put the existing code onto one line.

@DesWurstes
Copy link
Contributor Author

@tmthrgd

This can't be right for 0x09 (\t), because that would be \ (slash then tab).

Spaces and tabs are treated the same. These are allowed:

1) dnskey="a b"
2) dnskey=a\ b
3) dnskey="a\ b"

The current code uses the third form for experimental key=value pairs. It's easy to change it to the first, would you prefer the first?

They can share the same name: a = append(...).

If:

func areSVCBPairArraysEqual(a []SVCBKeyValue, b []SVCBKeyValue) bool {
	a := append([]SVCBKeyValue(nil), a...)
	b := append([]SVCBKeyValue(nil), b...)

Then:

./svcb.go:744:4: no new variables on left side of :=
./svcb.go:745:4: no new variables on left side of :=

Push 2 because can't build fuzzer python
Push 3 to try again
@ghedo
Copy link

ghedo commented Sep 18, 2020

Looks like this has gone silent for a while, any update? It seems most review comments have been addressed, but I guess @miekg hasn't had a chance to do his "minimization" pass yet?

And add the relevant test
Force push edit: Make sorting code fit into one line
Copy link
Collaborator

@tmthrgd tmthrgd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A handful of relatively minor changes, and then it should be ready to merge. Thanks for the patience.

msg_helpers.go Outdated Show resolved Hide resolved
msg_helpers.go Outdated Show resolved Hide resolved
msg_helpers.go Outdated Show resolved Hide resolved
svcb.go Outdated Show resolved Hide resolved
svcb.go Outdated Show resolved Hide resolved
}

func (s *SVCBIPv4Hint) parse(b string) error {
if strings.Contains(b, ":") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t love this check. Is there any harm in letting people use IPv4-in-IPv6 addresses?

svcb.go Outdated
}
x := make([]net.IP, 0, len(b)/16)
for i := 0; i < len(b); i += 16 {
x = append(x, net.IP(b[i:i+16]))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn’t check for IPv4 addresses, should it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's impossible to check for the address type, this is just a byte array.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A To4() != nil check was what I was referring to. Not sure if it’s a good idea, but it would seem consistent with other methods on this type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, if it's okay for you I would prefer not adding conditions that would always evaluate to one branch, To4() is always nil for 16-byte IP arrays.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems inconsistent with other methods on this type that all have a To4() != nil check on them. It’s definitely not going to be a hotspot.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, changed it.

}

func (s *SVCBIPv6Hint) parse(b string) error {
if strings.Contains(b, ".") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t like this check, just check To4() != nil inside the for-loop.

svcb.go Outdated
var str strings.Builder
str.Grow(4 * len(s.Data))
for _, e := range s.Data {
if (0x1f < e && e < 0x7f) || e == 0x09 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’d still like this to be clearer.

svcb.go Outdated Show resolved Hide resolved
@DesWurstes
Copy link
Contributor Author

DesWurstes commented Sep 27, 2020

Just to confirm the wire format is also base64 encoded?

Thank you, this used to be a broken implementation. I've now verified the correctness of its behavior with ghedo's Python tool.

I don’t love this check. Is there any harm in letting people use IPv4-in-IPv6 addresses?

This was to be consistent with #1107, unless something changed in the last few months?

@tmthrgd
Copy link
Collaborator

tmthrgd commented Sep 27, 2020

@DesWurstes

“This was to be consistent with #1107, unless something changed in the last few months?”

My memory apparently, months is a life time ago. 😅

If it’s consistent with elsewhere in this library, it’s fine to stay.

kerolasa pushed a commit to kerolasa/dns that referenced this pull request Oct 9, 2020
This branch exists to have pull 1067 changes on top of most recent upstream
miekg/master branch.

This branch took DesWurstes's master branch commit that diverged from commit
upstream commit 0ffcea3 and continued to
5cfc4ab.  The last commit 5cfc4ab... had
title 'More cleanup and fix mandatory not sorting bug'.

Reference: miekg#1067
Reference: https://github.com/DesWurstes/dns.git
Copy link
Collaborator

@tmthrgd tmthrgd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy with this now, no need to iterate ad infinitum over minor nits. Should be fine to merge. Thanks for your patience.

@miekg miekg merged commit 0972db6 into miekg:master Oct 11, 2020
@DesWurstes DesWurstes mentioned this pull request Feb 20, 2022
miekg pushed a commit that referenced this pull request Apr 1, 2022
* Rename ECH, bump draft number

* AliasForm new treatment

* alpn is no longer mandatory by default

* Document the non-empty value requirement

* new test cases

* more test cases

* Continue forbidding v4-map-v6 but not v4-embed-v6

#1067 (comment) and MikeBishop/dns-alt-svc#361

* Update documentation

* revert rename ech

* Reword AliasMode with key=value pairs
aanm pushed a commit to cilium/dns that referenced this pull request Jul 29, 2022
* Implement SVCB

* Fix serialization and deserialization of double quotes

* More effort (?)

4 months old commit

* DEBUG

* _

* Presentation format serialization/deserialization

* _

Remove generated

* Progress on presentation format parse & write

* _

* Finish parsing presentation format

* Regenerate

* Pack unpack

* Move to svcb.go

Scan_rr.go and types.go should be untouched now

* 🐛

Thanks ghedo

* Definitions

* TypeHTTPSSVC

* Generated

and isDuplicate

* Goodbye lenient functions

Now private key=value pairs have to be defined as structs too. They are no longer automatically named as KeyNNNNN

* Encode/decode

* Experimental svc

* Read method

* Implement some of the methods, use trick...

to  report where the error is while reading it. This should be applied to EDNS too. Todo: Find if case can only contain e := new(SVC_ALPN) and rest moved out

Also fix two compile errors

* Add SVC_LOCAL methods, reorder, remove alpn value, bugs

* Errors

* Alpn, make it build

* Correct testsuite

* Fully implement parser

Change from keeping a state variable to reading in one iteration until the key=value pair is fully consumed

* Simplify and document

EDNS should be simplified too

* Attempt to fix fuzzer

And Alpn bug

* A bug and change type values to match @ghedo's implementation

* IP bug

Also there are two ip duplicating patterns, one with copy, one with append. Maybe change it to be consistent.

* Check for strictly increasing keys as required

* Don't panic on invalid alpn

* Redundant check, don't modify original array

* Size calculation

* Fix the fuzzer, match the style

* 65535 is reserved too, don't delay errors

* Check keyNNN, check for aliasform having values

* IPvNHint is an array

* Fix ipvNHint

* Rename everything

* Unrecognized keys according to the updated specification

* Skip zero-length structs in generators. Fix CI

* Doc cleanup

* Off by one

* Add parse tests

* Check if private key doesn't collide with known key, invalid tests

* Disallow IPv4 as IPv6. More tests.

Related miekg#1107

* Style fixes

* More consistency, more tests

* 🐛 Deep copy as in the documentation

	a := make([]net.IP, 1)
	a[0] = net.ParseIP("1.1.1.1").To4()
	b := append(make([]net.IP, 0, 1), a...)
	b[0] = net.ParseIP("3.1.1.1").To4()
	fmt.Println(a[0][0])

* Make tests readable

* Move valid parse tests to different file

* 🐛 One of previous commits not fully committed

* Test binary single value encoding/decoding and full encode/decode

* Add worst-case grows to builders, 🐛 Wrong visible character range, redundant tests

* Testing improvements

And don't convert to IPv4 twice

* Doc update only

* Document worst case allocations

and ipv6 can be at most of length 39, not 40

* Redundant IP copy, consistent IPv6 behavior, fix deep copy

* isDuplicate for SVCB

* Optimizations

* echoconfig

* Svc => SVCB

* Fix CI

* Regenerate after REBASE (2)

Rebased twice on 15th and 20th May

* Rename svc, use escapeByte.

* Fix parsing whitespaces between quotes, rename ECHOHOConfig

* resolve

Remove svcbFieldLen
Use reverseInt
Uppercase SVCB
Rename key_value
"invalid" => bad
Alpn comments
> 65535 check
Unneeded slices

* a little more

read => parse
IP array meaning
Force pushed because forgot to change read in svcb_test.go

* HTTPSSVC -> HTTPS

* Use new values

* mandatory code

MikeBishop/dns-alt-svc#205

* Resolve comments

Rename svcb-pairs
Remove SVCB_PRIVATE ranges
Comment on SVCB_KEY65535
ParseError return l.token
rename svcbKeyToString and svcbStringToKey
privatize SVCBKeyToString, SVCBStringToKey

* Refactor 1

Rename sorted, originalPairs
Use append instead of copy
Use svcb_RESERVED instead of 65535, with it now being private
"type SVCBKey uint16"

* Refactor 2

svcbKeyToString as method
svcbStringToKey updated after key 0
:bug: mandatory has missing key
Rename str
idx < 0

* Refactor 3

Use l.token as z
var key, value string
Comment wrap
0:
Sentences with '.'
keyValue => kv

* Refactor 4

* Refactor 5

len() int

* Refactor 6

* Refactor 7

* Test remove parsing

* Error messages

* Rewrite two estimate comments

* parse shouldn't modify original array :bug:

* Remove two unneeded comments

* Address review comments

Push 2 because can't build fuzzer python
Push 3 to try again

* Simplify argument duplication as per tmthrgd's suggestion

And add the relevant test
Force push edit: Make sorting code fit into one line

* Rewrite ECHConfig and address the review

* Remove the optional tab

* Add To4() Check

* More cleanup and fix mandatory not sorting bug
aanm pushed a commit to cilium/dns that referenced this pull request Jul 29, 2022
* Rename ECH, bump draft number

* AliasForm new treatment

* alpn is no longer mandatory by default

* Document the non-empty value requirement

* new test cases

* more test cases

* Continue forbidding v4-map-v6 but not v4-embed-v6

miekg#1067 (comment) and MikeBishop/dns-alt-svc#361

* Update documentation

* revert rename ech

* Reword AliasMode with key=value pairs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

add SVCB record
6 participants